package cn.edu.nju.software.greencreditsystem.DAOImpl;

import cn.edu.nju.software.greencreditsystem.DAO.EnvironmentFactorDAO;
import cn.edu.nju.software.greencreditsystem.DAO.EnvironmentIndexDAO;
import cn.edu.nju.software.greencreditsystem.DAO.EnvironmentScoreDAO;
import cn.edu.nju.software.greencreditsystem.domain.EnvironmentFactor;
import cn.edu.nju.software.greencreditsystem.domain.EnvironmentIndex;
import cn.edu.nju.software.greencreditsystem.domain.EnvironmentScore;
import cn.edu.nju.software.greencreditsystem.factory.DAOFactory;
import cn.edu.nju.software.greencreditsystem.factory.SessionPool;
import java.awt.BasicStroke;
import java.util.List;
import org.hibernate.Query;
import org.hibernate.Session;
import java.awt.Color;
import java.awt.Font;
import java.awt.image.BufferedImage;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import org.jfree.chart.*;
import org.jfree.chart.annotations.XYLineAnnotation;
import org.jfree.chart.axis.*;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.*;
import org.jfree.data.time.*;

/**
 * 作者：何启睿
 * 创建时间：2011-8-19
 * 类描述：EnvironmentFactor类DAO实现
 */
public class EnvironmentFactorDAOImpl implements EnvironmentFactorDAO
{

    @Override
    public EnvironmentFactor getById(int id)
    {
        EnvironmentFactor result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        
        try
        {
            result = (EnvironmentFactor) s.get(EnvironmentFactor.class, id);
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }
        finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public EnvironmentFactor getByName(String name)
    {
        EnvironmentFactor result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        
        try
        {
            Query q = s.createQuery("from EnvironmentFactor where name = '" + name + "'");
            result = (EnvironmentFactor) q.uniqueResult();
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }
        finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public List<EnvironmentFactor> getByType(String type)
    {
        List<EnvironmentFactor> result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        
        try
        {
            Query q = s.createQuery("from EnvironmentFactor where type = '" + type + "'");
            result = q.list();
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }
        finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public List<EnvironmentFactor> getIndexFactor(int enterpriseID)
    {
        List<EnvironmentFactor> result = new ArrayList<EnvironmentFactor>();
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        
        try
        {
            Query q = s.createQuery("from EnvironmentIndex "
                                    + "where enterprise.id = " + enterpriseID
                                    + " order by factor.id");
            List<EnvironmentIndex> temp = q.list();
            for(int i = 0; i < temp.size(); i++)
                if(!result.contains(temp.get(i).getFactor()))
                    result.add(temp.get(i).getFactor());
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }
    
    @Override
    public List<EnvironmentFactor> getAllIndexFactor()
    {
        List<EnvironmentFactor> result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        
        try
        {
            Query q = s.createQuery("from EnvironmentFactor where type is not null");
            result = q.list();
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }
        finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public List<EnvironmentFactor> getAllScoreFactor()
    {
        List<EnvironmentFactor> result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        
        try
        {
            Query q = s.createQuery("from EnvironmentFactor where type is null");
            result = q.list();
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }
        finally
        {
            s.close();
        }
        
        return result;
    }
    
    @Override
    public boolean isIndex(int environmentFactorID)
    {
        Boolean result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            EnvironmentFactor ef = (EnvironmentFactor) s.get(EnvironmentFactor.class, environmentFactorID);
            if(ef.getType() == null)
                result = false;
            else
                result = true;
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }
    
    @Override
    public double getAverage(int environmentFactorID, Date date)
    {
        double result = 0;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        
        try
        {
            Calendar calendar = Calendar.getInstance();
            calendar.setTime(date);
            Date monthBegin = new Date(date.getYear(), date.getMonth(), 1);
            Date monthEnd = new Date(date.getYear(), date.getMonth(), calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
            
            Query q = null;
            if(isIndex(environmentFactorID))
                q = s.createQuery("select avg(value) from EnvironmentIndex "
                                    + "where factor.id = " + environmentFactorID
                                    + " and date between :begin and :end");
            else
                q = s.createQuery("select avg(value) from EnvironmentScore "
                                    + "where factor.id = " + environmentFactorID
                                    + " and date between :begin and :end");
            q.setDate("begin", monthBegin);
            q.setDate("end", monthEnd);
            result = (Double) q.uniqueResult();
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public BufferedImage drawImage(int enterpriseID, int environmentFactorID, Date begin, Date end, int width, int height)
    {
        BufferedImage result = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            String factorName = ((EnvironmentFactor) s.load(EnvironmentFactor.class, environmentFactorID)).getName();
            double standardValue = (Double) s.createQuery("select standardValue from EnvironmentStandardValue"
                                                + " where enterprise.id = " + enterpriseID
                                                + " and factor.id = " + environmentFactorID)
                                                .uniqueResult();
            s.getTransaction().commit();
            
            TimeSeries line = new TimeSeries("本企业" + factorName);
            TimeSeries avgLine = new TimeSeries("所有企业" + factorName +"均值");
            
            if(isIndex(environmentFactorID))
            {
                EnvironmentIndexDAO eidao = DAOFactory.getEnvironmentIndexDAOInstance();
                List<EnvironmentIndex> history = eidao.getHistoryIndex(enterpriseID, environmentFactorID, begin, end);
                Date date;
                double value;
                for(int i = 0; i < history.size(); i++)
                {
                    date = history.get(i).getDate();
                    value = history.get(i).getValue();
                    line.add(new Month(date.getMonth()+1, date.getYear()+1900), value);
                    
                    value = getAverage(environmentFactorID, date);
                    avgLine.add(new Month(date.getMonth()+1, date.getYear()+1900), value);
                }
            }
            else
            {
                EnvironmentScoreDAO fsdao = DAOFactory.getEnvironmentScoreDAOInstance();
                List<EnvironmentScore> history = fsdao.getHistoryScore(enterpriseID, environmentFactorID, begin, end);
                Date date;
                double value;
                for(int i = 0; i < history.size(); i++)
                {
                    date = history.get(i).getDate();
                    value = history.get(i).getValue();
                    line.add(new Month(date.getMonth()+1, date.getYear()+1900), value);
                    
                    value = getAverage(environmentFactorID, date);
                    avgLine.add(new Month(date.getMonth()+1, date.getYear()+1900), value);
                }
            }
            
            TimeSeriesCollection lineCollection = new TimeSeriesCollection();
            lineCollection.addSeries(line);
            lineCollection.addSeries(avgLine);
            
            JFreeChart chart = ChartFactory.createTimeSeriesChart("", "时间", "数值", lineCollection, true, true, false);
            chart.setBackgroundPaint(Color.WHITE);
            chart.getTitle().setFont(new Font("Helvetica",Font.PLAIN,13));
            chart.getLegend().setItemFont(new Font("Helvetica",Font.PLAIN,13));
            XYPlot plot = (XYPlot) chart.getPlot();
            if(plot.getRangeAxis().getUpperBound() < standardValue)
                plot.getRangeAxis().setUpperBound(standardValue + plot.getRangeAxis().getUpperBound()*0.1);
            if(plot.getRangeAxis().getLowerBound() > standardValue)
                plot.getRangeAxis().setLowerBound(standardValue - plot.getRangeAxis().getLowerBound()*0.1);
            plot.addAnnotation(new XYLineAnnotation(plot.getDomainAxis().getLowerBound(), 
                                                    standardValue, 
                                                    plot.getDomainAxis().getUpperBound(), 
                                                    standardValue, 
                                                    new BasicStroke(2), Color.BLACK));
            ((DateAxis) plot.getDomainAxis()).setTickUnit(new DateTickUnit(DateTickUnitType.MONTH, 1, new SimpleDateFormat("yyyy-MM")));
            plot.getDomainAxis().setLabelFont(new Font("Helvetica",Font.PLAIN,13));
            plot.getDomainAxis().setTickLabelFont(new Font("Helvetica",Font.PLAIN,13));
            plot.getRangeAxis().setLabelFont(new Font("Helvetica",Font.PLAIN,13));
            plot.getRangeAxis().setTickLabelFont(new Font("Helvetica",Font.PLAIN,13));
            plot.setBackgroundPaint(new Color(196, 225, 255));
            plot.setDomainGridlinePaint(Color.BLACK);
            plot.setRangeGridlinePaint(Color.BLACK);
            plot.setDomainCrosshairVisible(true);
            plot.setRangeCrosshairVisible(true);
            XYItemRenderer renderer = plot.getRenderer();
            if(renderer instanceof XYLineAndShapeRenderer)
            {
                XYLineAndShapeRenderer xylsRenderer = (XYLineAndShapeRenderer) renderer;
                xylsRenderer.setSeriesShapesVisible(0, true);
                xylsRenderer.setSeriesShapesFilled(0, true);
                xylsRenderer.setSeriesPaint(0, new Color(134, 0, 255));
                xylsRenderer.setSeriesShapesVisible(1, true);
                xylsRenderer.setSeriesShapesFilled(1, true);
                xylsRenderer.setSeriesPaint(1, new Color(255, 81, 81));
            }
            
            result = chart.createBufferedImage(width, height);
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }
        finally
        {
            s.close();
        }
        
        return result;
    }

    @Override
    public BufferedImage drawImage(int enterpriseID, int environmentFactorID, Date begin, Date end)
    {
        return drawImage(enterpriseID, environmentFactorID, begin, end, 600, 380);
    }

    @Override
    public BufferedImage drawImage(int enterpriseID, int environmentFactorID, int width, int height)
    {
        Date begin = null;
        Date end = null;
        
        Session s = SessionPool.getSession();
        s.beginTransaction();
        try
        {
            Query q;
            if(isIndex(environmentFactorID))
                q = s.createQuery("select date from EnvironmentIndex "
                                    + "where enterprise.id = " + enterpriseID
                                    + " and factor.id = " + environmentFactorID
                                    + " order by date asc");
            else
                q = s.createQuery("select date from EnvironmentScore "
                                    + "where enterprise.id = " + enterpriseID
                                    + " and factor.id = " + environmentFactorID
                                    + " order by date asc");
            List<Date> temp = q.list();
            begin = temp.get(0);
            end = temp.get(temp.size() - 1);
            s.getTransaction().commit();
        }catch(Exception ex)
        {
            ex.printStackTrace();
            s.getTransaction().rollback();
        }
        finally
        {
            s.close();
        }
        
        return drawImage(enterpriseID, environmentFactorID, begin, end, width, height);
    }

    @Override
    public BufferedImage drawImage(int enterpriseID, int environmentFactorID)
    {
        return drawImage(enterpriseID, environmentFactorID, 600, 380);
    }
}
